﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;

namespace MessagePack.Internal
{
	// Token: 0x02000118 RID: 280
	internal class ObjectSerializationInfo
	{
		// Token: 0x0600040E RID: 1038 RVA: 0x00011188 File Offset: 0x0000F588
		private ObjectSerializationInfo()
		{
		}

		// Token: 0x17000013 RID: 19
		// (get) Token: 0x0600040F RID: 1039 RVA: 0x00011190 File Offset: 0x0000F590
		// (set) Token: 0x06000410 RID: 1040 RVA: 0x00011198 File Offset: 0x0000F598
		public bool IsIntKey { get; set; }

		// Token: 0x17000014 RID: 20
		// (get) Token: 0x06000411 RID: 1041 RVA: 0x000111A1 File Offset: 0x0000F5A1
		public bool IsStringKey
		{
			get
			{
				return !this.IsIntKey;
			}
		}

		// Token: 0x17000015 RID: 21
		// (get) Token: 0x06000412 RID: 1042 RVA: 0x000111AC File Offset: 0x0000F5AC
		// (set) Token: 0x06000413 RID: 1043 RVA: 0x000111B4 File Offset: 0x0000F5B4
		public bool IsClass { get; set; }

		// Token: 0x17000016 RID: 22
		// (get) Token: 0x06000414 RID: 1044 RVA: 0x000111BD File Offset: 0x0000F5BD
		public bool IsStruct
		{
			get
			{
				return !this.IsClass;
			}
		}

		// Token: 0x17000017 RID: 23
		// (get) Token: 0x06000415 RID: 1045 RVA: 0x000111C8 File Offset: 0x0000F5C8
		// (set) Token: 0x06000416 RID: 1046 RVA: 0x000111D0 File Offset: 0x0000F5D0
		public ConstructorInfo BestmatchConstructor { get; set; }

		// Token: 0x17000018 RID: 24
		// (get) Token: 0x06000417 RID: 1047 RVA: 0x000111D9 File Offset: 0x0000F5D9
		// (set) Token: 0x06000418 RID: 1048 RVA: 0x000111E1 File Offset: 0x0000F5E1
		public ObjectSerializationInfo.EmittableMember[] ConstructorParameters { get; set; }

		// Token: 0x17000019 RID: 25
		// (get) Token: 0x06000419 RID: 1049 RVA: 0x000111EA File Offset: 0x0000F5EA
		// (set) Token: 0x0600041A RID: 1050 RVA: 0x000111F2 File Offset: 0x0000F5F2
		public ObjectSerializationInfo.EmittableMember[] Members { get; set; }

		// Token: 0x0600041B RID: 1051 RVA: 0x000111FC File Offset: 0x0000F5FC
		public static ObjectSerializationInfo CreateOrNull(Type type, bool forceStringKey)
		{
			TypeInfo_wzh typeInfo = type.GetTypeInfo_wzh();
			bool isClass = typeInfo.IsClass;
			MessagePackObjectAttribute customAttribute = typeInfo.GetCustomAttribute<MessagePackObjectAttribute>(true);
			if (customAttribute == null && !forceStringKey)
			{
				return null;
			}
			bool flag = true;
			Dictionary<int, ObjectSerializationInfo.EmittableMember> dictionary = new Dictionary<int, ObjectSerializationInfo.EmittableMember>();
			Dictionary<string, ObjectSerializationInfo.EmittableMember> dictionary2 = new Dictionary<string, ObjectSerializationInfo.EmittableMember>();
			//if (forceStringKey || customAttribute.KeyAsPropertyName)
			//{
			//	flag = false;
			//	int num = 0;
			//	foreach (PropertyInfo propertyInfo in type.GetRuntimeProperties())
			//	{
			//		if (propertyInfo.GetCustomAttribute(true) == null)
			//		{
			//			if (propertyInfo.GetCustomAttribute(true) == null)
			//			{
			//				ObjectSerializationInfo.EmittableMember emittableMember = new ObjectSerializationInfo.EmittableMember
			//				{
			//					PropertyInfo = propertyInfo,
			//					IsReadable = (propertyInfo.GetGetMethod() != null && propertyInfo.GetGetMethod().IsPublic && !propertyInfo.GetGetMethod().IsStatic),
			//					IsWritable = (propertyInfo.GetSetMethod() != null && propertyInfo.GetSetMethod().IsPublic && !propertyInfo.GetSetMethod().IsStatic),
			//					StringKey = propertyInfo.Name
			//				};
			//				if (emittableMember.IsReadable || emittableMember.IsWritable)
			//				{
			//					emittableMember.IntKey = num++;
			//					dictionary2.Add(emittableMember.StringKey, emittableMember);
			//				}
			//			}
			//		}
			//	}
			//	foreach (FieldInfo fieldInfo in type.GetRuntimeFields())
			//	{
			//		if (fieldInfo.GetCustomAttribute(true) == null)
			//		{
			//			if (fieldInfo.GetCustomAttribute(true) == null)
			//			{
			//				if (fieldInfo.GetCustomAttribute(true) == null)
			//				{
			//					if (!fieldInfo.IsStatic)
			//					{
			//						ObjectSerializationInfo.EmittableMember emittableMember2 = new ObjectSerializationInfo.EmittableMember
			//						{
			//							FieldInfo = fieldInfo,
			//							IsReadable = fieldInfo.IsPublic,
			//							IsWritable = (fieldInfo.IsPublic && !fieldInfo.IsInitOnly),
			//							StringKey = fieldInfo.Name
			//						};
			//						if (emittableMember2.IsReadable || emittableMember2.IsWritable)
			//						{
			//							emittableMember2.IntKey = num++;
			//							dictionary2.Add(emittableMember2.StringKey, emittableMember2);
			//						}
			//					}
			//				}
			//			}
			//		}
			//	}
			//}
			//else
			//{
			//	bool flag2 = true;
			//	int num2 = 0;
			//	foreach (PropertyInfo propertyInfo2 in type.GetRuntimeProperties())
			//	{
			//		if (propertyInfo2.GetCustomAttribute(true) == null)
			//		{
			//			if (propertyInfo2.GetCustomAttribute(true) == null)
			//			{
			//				ObjectSerializationInfo.EmittableMember emittableMember3 = new ObjectSerializationInfo.EmittableMember
			//				{
			//					PropertyInfo = propertyInfo2,
			//					IsReadable = (propertyInfo2.GetGetMethod() != null && propertyInfo2.GetGetMethod().IsPublic && !propertyInfo2.GetGetMethod().IsStatic),
			//					IsWritable = (propertyInfo2.GetSetMethod() != null && propertyInfo2.GetSetMethod().IsPublic && !propertyInfo2.GetSetMethod().IsStatic)
			//				};
			//				if (emittableMember3.IsReadable || emittableMember3.IsWritable)
			//				{
			//					KeyAttribute customAttribute2 = propertyInfo2.GetCustomAttribute(true);
			//					if (customAttribute2 == null)
			//					{
			//						throw new MessagePackDynamicObjectResolverException("all public members must mark KeyAttribute or IgnoreMemberAttribute. type: " + type.FullName + " member:" + propertyInfo2.Name);
			//					}
			//					if (customAttribute2.IntKey == null && customAttribute2.StringKey == null)
			//					{
			//						throw new MessagePackDynamicObjectResolverException("both IntKey and StringKey are null. type: " + type.FullName + " member:" + propertyInfo2.Name);
			//					}
			//					if (flag2)
			//					{
			//						flag2 = false;
			//						flag = (customAttribute2.IntKey != null);
			//					}
			//					else if ((flag && customAttribute2.IntKey == null) || (!flag && customAttribute2.StringKey == null))
			//					{
			//						throw new MessagePackDynamicObjectResolverException("all members key type must be same. type: " + type.FullName + " member:" + propertyInfo2.Name);
			//					}
			//					if (flag)
			//					{
			//						emittableMember3.IntKey = customAttribute2.IntKey.Value;
			//						if (dictionary.ContainsKey(emittableMember3.IntKey))
			//						{
			//							throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique. type: " + type.FullName + " member:" + propertyInfo2.Name);
			//						}
			//						dictionary.Add(emittableMember3.IntKey, emittableMember3);
			//					}
			//					else
			//					{
			//						emittableMember3.StringKey = customAttribute2.StringKey;
			//						if (dictionary2.ContainsKey(emittableMember3.StringKey))
			//						{
			//							throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique. type: " + type.FullName + " member:" + propertyInfo2.Name);
			//						}
			//						emittableMember3.IntKey = num2++;
			//						dictionary2.Add(emittableMember3.StringKey, emittableMember3);
			//					}
			//				}
			//			}
			//		}
			//	}
			//	foreach (FieldInfo fieldInfo2 in type.GetRuntimeFields())
			//	{
			//		if (fieldInfo2.GetCustomAttribute(true) == null)
			//		{
			//			if (fieldInfo2.GetCustomAttribute(true) == null)
			//			{
			//				if (fieldInfo2.GetCustomAttribute(true) == null)
			//				{
			//					if (!fieldInfo2.IsStatic)
			//					{
			//						ObjectSerializationInfo.EmittableMember emittableMember4 = new ObjectSerializationInfo.EmittableMember
			//						{
			//							FieldInfo = fieldInfo2,
			//							IsReadable = fieldInfo2.IsPublic,
			//							IsWritable = (fieldInfo2.IsPublic && !fieldInfo2.IsInitOnly)
			//						};
			//						if (emittableMember4.IsReadable || emittableMember4.IsWritable)
			//						{
			//							KeyAttribute customAttribute3 = fieldInfo2.GetCustomAttribute(true);
			//							if (customAttribute3 == null)
			//							{
			//								throw new MessagePackDynamicObjectResolverException("all public members must mark KeyAttribute or IgnoreMemberAttribute. type: " + type.FullName + " member:" + fieldInfo2.Name);
			//							}
			//							if (customAttribute3.IntKey == null && customAttribute3.StringKey == null)
			//							{
			//								throw new MessagePackDynamicObjectResolverException("both IntKey and StringKey are null. type: " + type.FullName + " member:" + fieldInfo2.Name);
			//							}
			//							if (flag2)
			//							{
			//								flag2 = false;
			//								flag = (customAttribute3.IntKey != null);
			//							}
			//							else if ((flag && customAttribute3.IntKey == null) || (!flag && customAttribute3.StringKey == null))
			//							{
			//								throw new MessagePackDynamicObjectResolverException("all members key type must be same. type: " + type.FullName + " member:" + fieldInfo2.Name);
			//							}
			//							if (flag)
			//							{
			//								emittableMember4.IntKey = customAttribute3.IntKey.Value;
			//								if (dictionary.ContainsKey(emittableMember4.IntKey))
			//								{
			//									throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique. type: " + type.FullName + " member:" + fieldInfo2.Name);
			//								}
			//								dictionary.Add(emittableMember4.IntKey, emittableMember4);
			//							}
			//							else
			//							{
			//								emittableMember4.StringKey = customAttribute3.StringKey;
			//								if (dictionary2.ContainsKey(emittableMember4.StringKey))
			//								{
			//									throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique. type: " + type.FullName + " member:" + fieldInfo2.Name);
			//								}
			//								emittableMember4.IntKey = num2++;
			//								dictionary2.Add(emittableMember4.StringKey, emittableMember4);
			//							}
			//						}
			//					}
			//				}
			//			}
			//		}
			//	}
			//}
			ConstructorInfo constructorInfo = null;
			//ConstructorInfo constructorInfo = (from x in typeInfo.DeclaredConstructors
			//                                   where x.IsPublic
			//                                   select x).SingleOrDefault((ConstructorInfo x) => x.GetCustomAttribute(false) != null);
			//if (constructorInfo == null)
			//{
			//	constructorInfo = (from x in typeInfo.DeclaredConstructors
			//	where x.IsPublic
			//	orderby x.GetParameters().Length
			//	select x).FirstOrDefault<ConstructorInfo>();
			//}
			//if (constructorInfo == null && isClass)
			//{
			//	throw new MessagePackDynamicObjectResolverException("can't find public constructor. type:" + type.FullName);
			//}
			List<ObjectSerializationInfo.EmittableMember> list = new List<ObjectSerializationInfo.EmittableMember>();
			if (constructorInfo != null)
			{
				ILookup<string, KeyValuePair<string, ObjectSerializationInfo.EmittableMember>> lookup = dictionary2.ToLookup((KeyValuePair<string, ObjectSerializationInfo.EmittableMember> x) => x.Key, (KeyValuePair<string, ObjectSerializationInfo.EmittableMember> x) => x, StringComparer.OrdinalIgnoreCase);
				int num3 = 0;
				foreach (ParameterInfo parameterInfo in constructorInfo.GetParameters())
				{
					if (flag)
					{
						ObjectSerializationInfo.EmittableMember value;
						if (!dictionary.TryGetValue(num3, out value))
						{
							throw new MessagePackDynamicObjectResolverException(string.Concat(new object[]
							{
								"can't find matched constructor parameter, index not found. type:",
								type.FullName,
								" parameterIndex:",
								num3
							}));
						}
						if (parameterInfo.ParameterType != value.Type || !value.IsReadable)
						{
							throw new MessagePackDynamicObjectResolverException(string.Concat(new object[]
							{
								"can't find matched constructor parameter, parameterType mismatch. type:",
								type.FullName,
								" parameterIndex:",
								num3,
								" paramterType:",
								parameterInfo.ParameterType.Name
							}));
						}
						list.Add(value);
					}
					else
					{
						IEnumerable<KeyValuePair<string, ObjectSerializationInfo.EmittableMember>> source = lookup[parameterInfo.Name];
						int num4 = source.Count<KeyValuePair<string, ObjectSerializationInfo.EmittableMember>>();
						if (num4 == 0)
						{
							throw new MessagePackDynamicObjectResolverException("can't find matched constructor parameter, index not found. type:" + type.FullName + " parameterName:" + parameterInfo.Name);
						}
						if (num4 != 1)
						{
							throw new MessagePackDynamicObjectResolverException(string.Concat(new string[]
							{
								"duplicate matched constructor parameter name:",
								type.FullName,
								" parameterName:",
								parameterInfo.Name,
								" paramterType:",
								parameterInfo.ParameterType.Name
							}));
						}
						ObjectSerializationInfo.EmittableMember value = source.First<KeyValuePair<string, ObjectSerializationInfo.EmittableMember>>().Value;
						if (parameterInfo.ParameterType != value.Type || !value.IsReadable)
						{
							throw new MessagePackDynamicObjectResolverException(string.Concat(new string[]
							{
								"can't find matched constructor parameter, parameterType mismatch. type:",
								type.FullName,
								" parameterName:",
								parameterInfo.Name,
								" paramterType:",
								parameterInfo.ParameterType.Name
							}));
						}
						list.Add(value);
					}
					num3++;
				}
			}
			return new ObjectSerializationInfo
			{
				IsClass = isClass,
				BestmatchConstructor = constructorInfo,
				ConstructorParameters = list.ToArray(),
				IsIntKey = flag,
				Members = ((!flag) ? dictionary2.Values.ToArray<ObjectSerializationInfo.EmittableMember>() : dictionary.Values.ToArray<ObjectSerializationInfo.EmittableMember>())
			};
		}

		// Token: 0x02000119 RID: 281
		public class EmittableMember
		{
			// Token: 0x1700001A RID: 26
			// (get) Token: 0x06000423 RID: 1059 RVA: 0x00011D60 File Offset: 0x00010160
			public bool IsProperty
			{
				get
				{
					return this.PropertyInfo != null;
				}
			}

			// Token: 0x1700001B RID: 27
			// (get) Token: 0x06000424 RID: 1060 RVA: 0x00011D6E File Offset: 0x0001016E
			public bool IsField
			{
				get
				{
					return this.FieldInfo != null;
				}
			}

			// Token: 0x1700001C RID: 28
			// (get) Token: 0x06000425 RID: 1061 RVA: 0x00011D7C File Offset: 0x0001017C
			// (set) Token: 0x06000426 RID: 1062 RVA: 0x00011D84 File Offset: 0x00010184
			public bool IsWritable { get; set; }

			// Token: 0x1700001D RID: 29
			// (get) Token: 0x06000427 RID: 1063 RVA: 0x00011D8D File Offset: 0x0001018D
			// (set) Token: 0x06000428 RID: 1064 RVA: 0x00011D95 File Offset: 0x00010195
			public bool IsReadable { get; set; }

			// Token: 0x1700001E RID: 30
			// (get) Token: 0x06000429 RID: 1065 RVA: 0x00011D9E File Offset: 0x0001019E
			// (set) Token: 0x0600042A RID: 1066 RVA: 0x00011DA6 File Offset: 0x000101A6
			public int IntKey { get; set; }

			// Token: 0x1700001F RID: 31
			// (get) Token: 0x0600042B RID: 1067 RVA: 0x00011DAF File Offset: 0x000101AF
			// (set) Token: 0x0600042C RID: 1068 RVA: 0x00011DB7 File Offset: 0x000101B7
			public string StringKey { get; set; }

			// Token: 0x17000020 RID: 32
			// (get) Token: 0x0600042D RID: 1069 RVA: 0x00011DC0 File Offset: 0x000101C0
			public Type Type
			{
				get
				{
					return (!this.IsField) ? this.PropertyInfo.PropertyType : this.FieldInfo.FieldType;
				}
			}

			// Token: 0x17000021 RID: 33
			// (get) Token: 0x0600042E RID: 1070 RVA: 0x00011DE8 File Offset: 0x000101E8
			// (set) Token: 0x0600042F RID: 1071 RVA: 0x00011DF0 File Offset: 0x000101F0
			public FieldInfo FieldInfo { get; set; }

			// Token: 0x17000022 RID: 34
			// (get) Token: 0x06000430 RID: 1072 RVA: 0x00011DF9 File Offset: 0x000101F9
			// (set) Token: 0x06000431 RID: 1073 RVA: 0x00011E01 File Offset: 0x00010201
			public PropertyInfo PropertyInfo { get; set; }

			// Token: 0x17000023 RID: 35
			// (get) Token: 0x06000432 RID: 1074 RVA: 0x00011E0C File Offset: 0x0001020C
			public bool IsValueType
			{
				get
				{
					MemberInfo memberInfo = (!this.IsProperty) ? this.FieldInfo : this.PropertyInfo;
					return memberInfo.DeclaringType.GetTypeInfo_wzh().IsValueType;
				}
			}

			// Token: 0x06000433 RID: 1075 RVA: 0x00011E46 File Offset: 0x00010246
			public void EmitLoadValue(ILGenerator il)
			{
				if (this.IsProperty)
				{
					il.EmitCall(this.PropertyInfo.GetGetMethod());
				}
				else
				{
					il.Emit(OpCodes.Ldfld, this.FieldInfo);
				}
			}

			// Token: 0x06000434 RID: 1076 RVA: 0x00011E7A File Offset: 0x0001027A
			public void EmitStoreValue(ILGenerator il)
			{
				if (this.IsProperty)
				{
					il.EmitCall(this.PropertyInfo.GetSetMethod());
				}
				else
				{
					il.Emit(OpCodes.Stfld, this.FieldInfo);
				}
			}
		}
	}
}
